import LayVmodelBase from "./LayVmodelBase.js";


/**工具包 */
var tools = {
    cmpId: function (prefix) {
        prefix = prefix || "cmp";
        return prefix + "_" + Math.random().toString(36).substring(2);
    },
    //创建控件属性变化观察者
    createElemObserver: function (elem, options) {
        var baseObsConfig = {
            attributes: true,
            childList: true,
            subtree: false,
            //回调
            attrChange: false, //function (attrName, newValue) { },属性变化回调
            remove: false, //function (elem) { },元素移除回调
        }
        var obsConfig = $.extend({}, baseObsConfig, options.obsConfig || {});

        var baseConfig = {
            obsConfig: obsConfig
        }

        var config = $.extend({}, baseConfig, options);

        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
        var observer = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                if (mutation.type === 'attributes') {
                    let newValue = $(elem).attr(mutation.attributeName);
                    config.attrChange && config.attrChange.call(observer, mutation.attributeName, newValue);
                }
                else if (mutation.type === 'childList') {
                    //判断被删除的元素是否是当前元素
                    let isRemove = mutation.find(x => x.removedNodes.find(y => y == elem)) != null;
                    if (isRemove) {
                        config.remove && config.remove.call(observer, elem);
                    }
                }
            });
        });

        observer.observe(elem, config.obsConfig);
        return observer;
    },
    hash: {
        _hashObjCacheMap: [],
        newHash: function () {
            var hash = Math.random().toString(36).substring(2);
            return hash;
        },
        hashCode: function (obj) {
            if (typeof obj === "string" || typeof obj === "number") {
                return obj.toString();
            }
            let hashEnty = this._hashObjCacheMap.find(x => x.objkey == obj);
            if (hashEnty) {
                return hashEnty.hashCode;
            }

            let hash = this.newHash();
            this._hashObjCacheMap.push({
                objkey: obj,
                hashCode: hash
            });

            return hash;
        }
    },
    /**array 根据内容比较是否相等 */
    arrayEquals: function (array1, array2) {
        if (!array1 && !array2) return true;
        if (!array1 || !array2) return false;
        if (array1.length != array2.length) return false;
        for (var i = 0; i < array1.length; i++) {
            if (array1[i] !== array2[i]) return false;
        }
        return true;
    },
    hook: {
        //自动属性方式劫持
        defineKidnapAutoProp: function (data, key, val, hook) {
            Object.defineProperty(data, key, {
                get: function () {
                    let res = val;
                    if (hook && hook.beforeGet) {
                        let args = {
                            key: key,
                            result: val,
                            data: data
                        }
                        hook.beforeGet.call(data, args);
                        res = args.result;
                    }
                    return res;
                },
                set: function (newVal) {
                    if (val === newVal) return;
                    let setValue = newVal;
                    function createEventArgs() {
                        return {
                            key: key,
                            newVal: newVal,
                            data: data,
                            oldValue: val,
                            newValue: newVal
                        }
                    }
                    if (hook && hook.beforeSet) {
                        let args = createEventArgs();
                        let canset = hook.beforeSet.call(data, args);
                        if (canset === false) return;
                        setValue = args.newValue;
                    }
                    val = setValue;
                    if (hook && hook.afterSet) {
                        let args = createEventArgs();
                        hook.afterSet.call(data, args);
                    }
                }
            });
        },
        //函数方式劫持
        defineKidnapFunction: function (data, key, val, hook) {
            data[key] = function (newVal) {
                //get
                if (newVal === undefined) {
                    let res = val;
                    if (hook && hook.beforeGet) {
                        let args = {
                            key: key,
                            result: val,
                            data: data
                        }
                        hook.beforeGet.call(data, args);
                        res = args.result;
                    }
                    return res;
                }
                //set
                else {
                    if (val === newVal) return;
                    let setValue = newVal;
                    function createEventArgs() {
                        return {
                            key: key,
                            newVal: newVal,
                            data: data,
                            oldValue: val,
                            newValue: newVal
                        }
                    }
                    if (hook && hook.beforeSet) {
                        let args = createEventArgs();
                        let canset = hook.beforeSet.call(data, args);
                        if (canset === false) return;
                        setValue = args.newValue;
                    }
                    val = setValue;
                    if (hook && hook.afterSet) {
                        let args = createEventArgs();
                        hook.afterSet.call(data, args);
                    }
                }
            }
        }
    },
    laymod: function (name) {
        if (layui[name]) {
            return layui[name];
        }
        layui.use(name);
        if (!layui[name]) {
            throw new Error(`layui 加载${name}模块失败，请在执行 ko.applyBindings 之前引入该模块或使用全模块layui版本`);
        }
        return layui[name];
    }
}



/**日志器 */
var logger = {
    logWran: function (msg) {
        console.warn(msg);
    },
    logError: function (msg) {
        console.error(msg);
    },
    logDebug: function (msg) {
        console.debug(msg);
    }
}

/**运行时数据 */
var runtime = {
    /**layChecked 数据槽 */
    layCheckedSlot: {

        //layChecked 数组访问器列表
        checkArrayAccessors: [],
        /**
         * 
         * @param {*} id 
         * @returns {CheckedArrayAccessor}
         */
        getAACbyId: function (id) {
            return this.checkArrayAccessors.find(x => x.id == id);
        }
    },
    /**layRadio 数据槽 */
    layRadioSlot: {
        radioEventCenter: {},
        onChecked: function (layfilter, callback) {
            var tis = this;
            if (!this.radioEventCenter[layfilter]) {
                this.radioEventCenter[layfilter] = [];
                let form = tools.laymod('form');
                //绑定元素到vmodel,  不要使用lay-filter,因为带有lay-filter会独占事件
                form.on(`radio`, function (data) {
                    var elem = data.elem; // 获得 checkbox 原始 DOM 对象
                    var checked = elem.checked; // 获得 checkbox 选中状态
                    var value = elem.value; // 获得 radio 值
                    var etis = this;
                    if ($(elem).attr("lay-filter") !== layfilter) return;

                    tis.radioEventCenter[layfilter].forEach(x => {
                        x.call(etis, data);
                    });
                });
            }

            this.radioEventCenter[layfilter].push(callback);
        }
    },
}

export {
    tools,
    logger,
    runtime
}